#include <iostream>
#include "Complex.h"
#include "ComplexRegular.h"
#include "Name.h"
using namespace std;

//1.定义了全局函数
Complex myAdd(Complex &c1, Complex &c2)
{
        Complex tmp(c1.a+c2.a, c1.b+c2.b);
        return tmp;
}

//
Complex operator+(Complex &c1, Complex &c2){
        Complex tmp(c1.a+c2.a, c1.b+c2.b);
        return tmp;
}

//前置++
Complex& operator++(Complex &c)
{
        c.a++;
        c.b++;
        return c;
}

//后置++ 
//由于已经有了前置++ 函数重载会出问题 所以加一个占位符来区分
Complex operator++(Complex &c, int)
{
        //先使用 在让c++  为了达到效果要将c先保存起来
        Complex tmp = c;
        c.a++;
        c.b++;
        return tmp;
}

int main01(int argc, char const *argv[])
{
        int a =0 , b = 0;
        int c;
        c = a+b;//1.基础数据类型 c++编译器已经知道了， 如何运算

        Complex c1(1,2), c2(3, 4);
        //Complex c3; //2.类 是一种数据类型 用户自定义类型 c++编译器 是不知道如何进行运算
        //c3 = c1 + c2;

        //3.c++编译器应该给我们程序员提供一种机制...
        //让自定义数据类型 有机会 进行 运算符重载机制

        //4.运算符重载机制
        //Complex c4 =  myAdd(c1, c2);

        //Complex c4 = operator+(c1, c2);
        
        Complex c4 = c1 + c2;

        c4.printComplex();

        //总结: 1 运算符重载的本质 是 函数调用

        return 0;
}

/*
全局函数,类的成员函数方法实现运算符重载步骤
        1.要承认操作符重载是一个函数,写出函数名称
        2.根据操作数,写出函数参数
        3.根据业务,完善函数返回值(看函数是返回引用 还是指针 元素 )，及实现函数业务
                引用用在一元元素的操作 比如++
                全局函数为了能够在函数体内使用类的似有变量还要 将全局函数声明为类的好朋友
*/
int main02(int argc, char const *argv[])
{
        Complex c1(1,2), c2(3, 4);
        Complex c3 = c1 - c2;
        c3.printComplex();    
        
        //前置++ 用全局函数是实现
        ++c3; 
        //Complex& operator++(Complex &c)
        c3.printComplex();

        //前置-- 用成员函数是实现
        --c3;
        c3.printComplex();
        //c1.operator--()
        //Complex& operator--()

        //后置++ 用全局函数是实现
        Complex c4 = c3++;
        c4.printComplex();
        c3.printComplex();
        //Complex operator++(Complex &c)

        //后置-- 用成员函数是实现
        c3--;
        c3.printComplex();
        //c1.operator--()
        //Complex operator--()

        return 0;
}

//运算符重载正规写法 一般都是写在成员函数里边
int main03(int argc, char const *argv[]){
        ComplexRegular c1(1, 2), c2(3, 4);

        ComplexRegular c3 = c1+c2;
        c3.printComplex();

        ++c3;
        c3.printComplex();

        ComplexRegular c4 =  c3++;
        c4.printComplex();
        c3.printComplex();

        --c3;
        c3.printComplex();

        ComplexRegular c5 = c3--;
        c5.printComplex();
        c3.printComplex();

        ComplexRegular c6 = c2-c1;
        c6.printComplex();

        return 0;
}

//重载左移操作符
ostream& operator<<(ostream &out, ComplexRegular &c)
{
        cout<<"12345 生活真辛苦 ";
        cout<<c.a<<" + "<<c.b<<"i ";
        return out;
}

//友元函数真正的使用场景
int main04(int argc, char const *argv[])
{
        int  a = 10;
        ComplexRegular c1(1, 2), c2(3, 4);       
        cout<<a<<endl;//按照数据类型

        //向这种场景要使用到输入输出流 只能使用全局函数来实现
        //因为你拿不到 cout的源代码 
        cout<<c1<<"aaaa"<<endl;
        
        return 0;
}


//重载=号操作符并实现深拷贝
//一个类中存在char*  默认赋值时浅拷贝在释放内存时会报错
void objectPlay()
{
        Name obj1("abcdefgh");
        Name obj2("aa");
        obj2 = obj1;
        //obj2.operator=(obj1)
        //Name& operator=(Name &obj)
        
        Name obj3("obj3");
        obj1 = obj2 = obj3;
}

int main(int argc, char const *argv[])
{
        objectPlay();
        return 0;
}

